package com.belf.console.service.impl;

import com.belf.console.domain.DataSourceInfo;
import com.belf.console.domain.DataTaskConf;
import com.belf.console.domain.entity.*;
import com.belf.console.service.IDataSourceInfoService;
import com.belf.console.service.IDataTaskConfService;
import com.belf.console.service.PromtHelperService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;

/**
 * PromtHelperServiceImpl
 *
 * @author l
 * @since 2024/11/4 16:49
 */
@Service
public class PromtHelperServiceImpl implements PromtHelperService {

    @Autowired
    private IDataTaskConfService dataTaskConfService;
    @Autowired
    private IDataSourceInfoService dataSourceInfoService;

    @Override
    public ArrayList<String> getKeyword(PromtHelper promtHelper) {
        //  查询任务信息
        DataTaskConf dataTaskConf = dataTaskConfService.selectDataTaskConfById(promtHelper.getTaskId());
        DataSourceInfo sourceData = dataSourceInfoService.selectDataSourceInfoById(dataTaskConf.getSourceId());
        String sourceCatalog = sourceData.getType();

        DataSourceInfo sinkData = dataSourceInfoService.selectDataSourceInfoById(dataTaskConf.getSinkId());
        String sinkCatalog = sinkData.getType();

        String sinkDatabase = dataTaskConf.getSinkDatabase();
        String sinkDataSchema = dataTaskConf.getSinkDataSchema();

        String quote = sinkData.getQuote();
        String fieldCase = sinkData.getFieldCase();

        //  构建关键词
        return requirement(
                sourceCatalog,
                sinkCatalog,
                sinkDataSchema,
                new QualifiersModel("\"", "\"", fieldCase, "COLON"),
                promtHelper.getObjectType());
    }

    /**
     * 构造SQL转换的个性化条件
     * @param sourceCatalog 源端数据库类型，取值参考{@link DatabaseIdentifier}
     * @param sinkCatalog 目标端数据库类型，取值参考{@link DatabaseIdentifier}
     * @param sinkSchema 目标端数据库的schema
     * @param sinkQualifiersModel 目标端数据库的SQL语句的个性化设置
     * @param objectType 本次转换的SQL对象类型，取值参考{@link DbObjectType}
     * @return
     */
    public ArrayList<String> requirement(String sourceCatalog,
                                     String sinkCatalog,
                                     String sinkSchema,
                                     QualifiersModel sinkQualifiersModel,
                                         String dbObjectType) {
        ArrayList<String> resultList = new ArrayList<>();
        resultList.add(fieldCase(sinkQualifiersModel));

        String quotation = quote(sinkQualifiersModel, sourceCatalog, sinkCatalog);
        if (StringUtils.isNotEmpty(quotation)) {
            resultList.add(quotation);
        }
//        ObjectType objectType = ObjectType.getObjectType(objectType);
        String schemaRequire = schema(sinkSchema, dbObjectType);
        if (StringUtils.isNotEmpty(schemaRequire)) {
            resultList.add(schemaRequire);
        }
        String connectionSymbol = connectionSymbol(sinkQualifiersModel);
        if (StringUtils.isNotEmpty(connectionSymbol)) {
            resultList.add(connectionSymbol);
        }
        //如果目标端非MySQL兼容的数据库，对于函数和存储过程，DECLARE一般要放到CREATE和BEGIN之间
        if (!(DatabaseCompatibility.name(sinkSchema).equals("MySQL"))) {

            DbObjectType objectType = DbObjectType.getDbObjectType(dbObjectType);
            if (objectType == DbObjectType.PROCEDURE
                    || objectType == DbObjectType.FUNCTION) {
                resultList.add("\n如果有DECLARE语句，需要提到BEGIN语句之前；");
            }
        }
        return resultList;
    }

    /**
     * 大小写转换要求
     * @param sinkQualifiersModel
     * @return
     */
    public static String fieldCase(QualifiersModel sinkQualifiersModel) {
        FieldCase fieldCase = FieldCase.getFieldCase(sinkQualifiersModel.getFieldCase());
        switch (fieldCase) {
            case LOWERCASE:
                return "转换要求：\nSQL语句中的标识符全部改为小写；";
            case UPPERCASE:
                return "转换要求：\nSQL语句中的标识符全部改为大写；";
            default:
                return "转换要求：";
        }
    }

    /**
     * 表示名称是否加引号
     * @param sinkQualifiersModel
     * @param sourceCatalog
     * @param sinkCatalog
     * @return
     */
    public static String quote(QualifiersModel sinkQualifiersModel, String sourceCatalog, String sinkCatalog) {
        if (StringUtils.isEmpty(sinkQualifiersModel.getLeftQuote())) {
            return null;
        }
        if (sinkQualifiersModel.getLeftQuote().equals("\"")) {
            if (sourceCatalog.equals(DatabaseIdentifier.SQLSERVER)) {
                return "\n所有标识名称（包括模式名、表名、视图名、字段名等）的方括号替换为双引号；";
            } else {
                return "\n给所有标识名称（包括模式名、表名、视图名、字段名等）加上双引号；";
            }
        }
        return null;
    }

    /**
     * 是否要添加schema前缀
     * @param sinkSchema
     * @return
     */
    public static String schema(String sinkSchema, String dbObjectType) {
        if (StringUtils.isEmpty(sinkSchema)) {
            return null;
        }
        DbObjectType objectType = DbObjectType.getDbObjectType(dbObjectType);

        String objectName = "";
        if (objectType == DbObjectType.PROCEDURE
                || objectType == DbObjectType.FUNCTION) {
            objectName = objectType.chineseName() + "名称、";
        }
        String result = String.format("\n没有模式前缀的%s表名和视图名前面要加上模式名称%s；",
                objectName,
                sinkSchema);

        return result;
    }

    public static String connectionSymbol(QualifiersModel sinkQualifiersModel) {
        if (sinkQualifiersModel.getQualifiedType() == QualifiedType.COLON.getEscapeValue()) {
            return "\n模式名称和表名、视图名之间用冒号连接；";
        }
        return null;
    }


}
